package com.whfc.common.third.bimface;

import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.third.bimface.entity.*;
import com.whfc.common.util.Base64Util;
import com.whfc.common.util.HttpUtil;
import com.whfc.common.util.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @author: xugcheng
 * @version: 1.0
 * @date: 2021-09-09 17:16
 */
public class BimfaceApi {

    private static final Logger logger = LoggerFactory.getLogger(BimfaceApi.class);

    private static final String SUCCESS = "success";

    private static final String ACCESS_TOKEN_URL = "https://api.bimface.com/oauth2/token";

    private static final String VIEW_TOKEN_URL = "https://api.bimface.com/view/token";

    private static final String SHARE_URL = "https://api.bimface.com/share";

    private static final String UPLOAD_URL = "https://file.bimface.com/upload";

    private static final String UPLOAD_POLICY_URL = "https://file.bimface.com/upload/policy";

    private static final String FILES_URL = "https://file.bimface.com/files/%s";

    private static final String FILES_STATUS_URL = "https://file.bimface.com/files/%s/uploadStatus";

    private static final String FILES_SUPPORT_URL = "https://file.bimface.com/support";

    private static final String FILES_DOWNLOAD_URL = "https://file.bimface.com/download/url";

    private static final String TRANSLATE_URL = "https://api.bimface.com/translate";

    private static final String TRANSLATE_DETAIL_URL = "https://api.bimface.com/translateDetails";

    private static final String INTEGRATE_URL = "https://api.bimface.com/integrate";

    private static final String COMPARE_URL = "https://api.bimface.com/v2/compare";

    /**
     * 获取accessToken
     *
     * @param appKey
     * @param appSecret
     * @return
     */
    public static AccessToken getAccessToken(String appKey, String appSecret) {

        String base64 = Base64Util.encodeToString(appKey + ":" + appSecret);
        String basicAuth = String.format("Basic %s", base64);
        Map<String, String> headers = new HashMap<>(1);
        headers.put("Authorization", basicAuth);
        String response = HttpUtil.doPost(ACCESS_TOKEN_URL, "", headers);
        logger.info("获取accessToken,response:{}", response);
        Result result = JSONUtil.parseObject(response, Result.class);
        String data = result == null ? null : result.getData();
        return JSONUtil.parseObject(data, AccessToken.class);
    }

    /**
     * 获取viewToken
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static String getViewToken(String accessToken, String fileId) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = VIEW_TOKEN_URL + "?fileId=" + fileId;
        String response = HttpUtil.doGet(url, headers);
        logger.info("查询viewToken,fileId:{},response:{}", fileId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return result.getData();
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "获取viewToken失败");
    }

    /**
     * 获取viewToken
     *
     * @param accessToken
     * @param fileId
     * @param fileType    fileId 文件转换ID
     *                    integrateId 集成模型ID
     *                    compareId 模型对比ID
     *                    sceneId 	场景ID
     *                    submodelId  子模型ID
     *                    clashDetectiveId 碰撞检测ID
     * @return
     */
    public static String getViewToken(String accessToken, String fileId, String fileType) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = String.format("%s?%s=%s", VIEW_TOKEN_URL, fileType, fileId);
        String response = HttpUtil.doGet(url, headers);
        logger.info("查询viewToken,fileId:{},response:{}", fileId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return result.getData();
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "获取viewToken失败");
    }

    /**
     * 生成分享链接
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static ShareUrl createShareUrl(String accessToken, String fileId) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = SHARE_URL + "?fileId=" + fileId;
        String response = HttpUtil.doPost(url, "", headers);
        logger.info("获取shareUrl,fileId:{},response:{}", fileId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        String data = result == null ? null : result.getData();
        return JSONUtil.parseObject(data, ShareUrl.class);
    }

    /**
     * 指定外部文件url方式上传
     *
     * @param accessToken
     * @param fileName    文件名
     * @param fileUrl     文件url
     */
    public static BimFile uploadUrl(String accessToken, String fileName, String fileUrl) {
        String url = new StringBuilder(UPLOAD_URL)
                .append("?name=").append(fileName)
                .append("&url=").append(fileUrl)
                .toString();
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doPut(url, headers);
        logger.info("上传bim模型,fileUrl:{},response:{}", fileUrl, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), BimFile.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "上传BIM模型失败");
    }

    /**
     * 获取文件直传的policy凭证
     *
     * @param accessToken
     * @param fileName
     */
    public static UploadPolicy uploadPolicy(String accessToken, String fileName) {
        String url = new StringBuilder(UPLOAD_POLICY_URL)
                .append("?name=").append(fileName)
                .toString();
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doGet(url, headers);
        Result result = JSONUtil.parseObject(response, Result.class);
        String data = result == null ? null : result.getData();
        return JSONUtil.parseObject(data, UploadPolicy.class);
    }

    /**
     * 获取文件信息
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static BimFile fileInfo(String accessToken, String fileId) {
        String url = String.format(FILES_URL, fileId);
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doGet(url, headers);
        logger.info("BimfaceApi--fileInfo--response:" + response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), BimFile.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "获取文件信息失败");
    }

    /**
     * 获取文件上传状态
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static BimFileStatus fileUploadStatus(String accessToken, String fileId) {
        String url = String.format(FILES_STATUS_URL, fileId);
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doGet(url, headers);
        logger.info("BimfaceApi--fileUploadStatus--response:" + response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), BimFileStatus.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "获取文件上传状态失败");
    }

    /**
     * 获取支持的文件类型
     *
     * @param accessToken
     * @return
     */
    public static BimFileSupport fileSupport(String accessToken) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doGet(FILES_SUPPORT_URL, headers);
        Result result = JSONUtil.parseObject(response, Result.class);
        String data = result == null ? null : result.getData();
        return JSONUtil.parseObject(data, BimFileSupport.class);
    }

    /**
     * 获取文件下载地址
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static String fileDownloadUrl(String accessToken, String fileId) {
        String url = FILES_DOWNLOAD_URL + "?fileId=" + fileId;
        Map<String, String> headers = buildBearerAuth(accessToken);
        String response = HttpUtil.doGet(url, headers);
        Result result = JSONUtil.parseObject(response, Result.class);
        return result == null ? null : result.getData();
    }

    /**
     * 发起文件转换
     *
     * @param accessToken
     * @param source
     * @param config
     * @param callback
     */
    public static TranslateResult translateFile(String accessToken, TranslateSource source, Map<String, Object> config, String callback) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        Map<String, Object> body = new HashMap<>(3);
        body.put("source", source);
        body.put("config", config);
        body.put("callback", callback);
        String response = HttpUtil.doPut(TRANSLATE_URL, headers, JSONUtil.toString(body));
        logger.info("BimfaceApi--translateFileStatus, response:{}", response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), TranslateResult.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "BIM模型文件转换失败");
    }

    /**
     * 查询文件转换
     *
     * @param accessToken
     * @param fileId
     * @return
     */
    public static TranslateResult translateFileStatus(String accessToken, String fileId) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = TRANSLATE_URL + "?fileId=" + fileId;
        String response = HttpUtil.doGet(url, headers);
        logger.info("BimfaceApi--translateFileStatus, fileId:{}, response:{}", fileId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), TranslateResult.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "解析模型ID错误");

    }

    /**
     * 集成模型状态
     *
     * @param accessToken
     * @param integrateId 集成模型ID
     */
    public static IntegrateResult integrateStatus(String accessToken, String integrateId) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = INTEGRATE_URL + "?integrateId=" + integrateId;
        String response = HttpUtil.doGet(url, headers);
        logger.info("BimfaceApi--integrateStatus, integrateId:{}, response:{}", integrateId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), IntegrateResult.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "解析集成模型ID错误");
    }

    /**
     * 模型对比状态
     *
     * @param accessToken
     * @param compareId   集成模型ID
     */
    public static CompareResult compareStatus(String accessToken, String compareId) {
        Map<String, String> headers = buildBearerAuth(accessToken);
        String url = COMPARE_URL + "?compareId=" + compareId;
        String response = HttpUtil.doGet(url, headers);
        logger.info("BimfaceApi--compareStatus, compareId:{}, response:{}", compareId, response);
        Result result = JSONUtil.parseObject(response, Result.class);
        if (result != null && SUCCESS.equalsIgnoreCase(result.getCode())) {
            return JSONUtil.parseObject(result.getData(), CompareResult.class);
        }
        throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "解析模型对比ID错误");
    }

    /**
     * 授权header
     *
     * @param accessToken
     * @return
     */
    private static Map<String, String> buildBearerAuth(String accessToken) {
        String bearAuth = String.format("Bearer %s", accessToken);
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", bearAuth);
        return headers;
    }
}
